/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    mutable_transmutes,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    unused_unsafe,
    clippy::never_loop
)]
use crate::common::*;
extern "C" {
    fn umask(__mask: __mode_t) -> __mode_t;
    fn __xstat(
        __ver: libc::c_int,
        __filename: *const libc::c_char,
        __stat_buf: *mut stat,
    ) -> libc::c_int;
    fn waitpid(__pid: __pid_t, __stat_loc: *mut libc::c_int, __options: libc::c_int) -> __pid_t;
    fn fclose(__stream: *mut FILE) -> libc::c_int;
    fn fflush(__stream: *mut FILE) -> libc::c_int;
    fn fopen(_: *const libc::c_char, _: *const libc::c_char) -> *mut FILE;
    fn fdopen(__fd: libc::c_int, __modes: *const libc::c_char) -> *mut FILE;
    fn fprintf(_: *mut FILE, _: *const libc::c_char, _: ...) -> libc::c_int;
    fn snprintf(
        _: *mut libc::c_char,
        _: libc::c_ulong,
        _: *const libc::c_char,
        _: ...
    ) -> libc::c_int;
    fn asprintf(__ptr: *mut *mut libc::c_char, __fmt: *const libc::c_char, _: ...) -> libc::c_int;
    fn fputc(__c: libc::c_int, __stream: *mut FILE) -> libc::c_int;
    fn fputs(__s: *const libc::c_char, __stream: *mut FILE) -> libc::c_int;
    fn ferror(__stream: *mut FILE) -> libc::c_int;
    fn fileno(__stream: *mut FILE) -> libc::c_int;
    fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn memrchr(__s: *const libc::c_void, __c: libc::c_int, __n: size_t) -> *mut libc::c_void;
    fn strcmp(_: *const libc::c_char, _: *const libc::c_char) -> libc::c_int;
    fn strdup(_: *const libc::c_char) -> *mut libc::c_char;
    fn strrchr(_: *const libc::c_char, _: libc::c_int) -> *mut libc::c_char;
    fn strtok_r(
        __s: *mut libc::c_char,
        __delim: *const libc::c_char,
        __save_ptr: *mut *mut libc::c_char,
    ) -> *mut libc::c_char;
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn strerror(_: libc::c_int) -> *mut libc::c_char;
    fn close(__fd: libc::c_int) -> libc::c_int;
    fn pipe(__pipedes: *mut libc::c_int) -> libc::c_int;
    fn chdir(__path: *const libc::c_char) -> libc::c_int;
    fn dup2(__fd: libc::c_int, __fd2: libc::c_int) -> libc::c_int;
    fn execv(__path: *const libc::c_char, __argv: *const *mut libc::c_char) -> libc::c_int;
    fn _exit(_: libc::c_int) -> !;
    fn setsid() -> __pid_t;
    fn fork() -> __pid_t;
    fn nl_langinfo(__item: nl_item) -> *mut libc::c_char;
    fn gai_strerror(__ecode: libc::c_int) -> *const libc::c_char;
    fn time(__timer: *mut time_t) -> time_t;
    fn __ctype_b_loc() -> *mut *const libc::c_ushort;
    fn __errno_location() -> *mut libc::c_int;
    fn open(__file: *const libc::c_char, __oflag: libc::c_int, _: ...) -> libc::c_int;
    fn closelog();
    fn openlog(__ident: *const libc::c_char, __option: libc::c_int, __facility: libc::c_int);
    fn sudo_warn_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    static mut sudo_defs_table: [sudo_defs_types; 0];
    static mut NewArgc: libc::c_int;
    static mut NewArgv: *mut *mut libc::c_char;
    fn sudoers_setlocale(newlocale: libc::c_int, prevlocale: *mut libc::c_int) -> bool;
    fn audit_failure(
        argc: libc::c_int,
        argv: *mut *mut libc::c_char,
        fmt: *const libc::c_char,
        _: ...
    ) -> libc::c_int;
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
    fn restore_perms() -> bool;
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    static mut sudo_user: sudo_user;
    fn get_timestr(_: time_t, _: libc::c_int) -> *mut libc::c_char;
    fn sudo_strlcat(dst: *mut libc::c_char, src: *const libc::c_char, siz: size_t) -> size_t;
    fn set_perms(_: libc::c_int) -> bool;
    fn sudo_closefrom(_: libc::c_int);
    fn sudo_debug_fork_v1() -> pid_t;
    fn sudo_debug_get_fds_v1(fds: *mut *mut libc::c_uchar) -> libc::c_int;
    fn dcngettext(
        __domainname: *const libc::c_char,
        __msgid1: *const libc::c_char,
        __msgid2: *const libc::c_char,
        __n: libc::c_ulong,
        __category: libc::c_int,
    ) -> *mut libc::c_char;
    fn dcgettext(
        __domainname: *const libc::c_char,
        __msgid: *const libc::c_char,
        __category: libc::c_int,
    ) -> *mut libc::c_char;
    static mut sudo_mode: libc::c_int;
    fn writeln_wrap(
        fp: *mut FILE,
        line: *mut libc::c_char,
        len: size_t,
        maxlen: size_t,
    ) -> libc::c_int;
    fn sudo_lock_file_v1(fd: libc::c_int, action: libc::c_int) -> bool;
    static mut list_pw: *mut passwd;
    static mut sudo_printf:
        Option<unsafe extern "C" fn(libc::c_int, *const libc::c_char, ...) -> libc::c_int>;

    fn mysyslog(pri: libc::c_int, fmt: *const libc::c_char, args: ...);
    fn log_warning(flags: libc::c_int, fmt: *const libc::c_char, args: ...) -> bool;
    fn log_warningx(flags: libc::c_int, fmt: *const libc::c_char, args: ...) -> bool;
    fn gai_log_warning(
        flags: libc::c_int,
        errnum: libc::c_int,
        fmt: *const libc::c_char,
        args: ...
    ) -> bool;
    fn send_mail(fmt: *const libc::c_char, args: ...) -> bool;

}

pub const MAXSYSLOGTRIES: libc::c_int = 16; /* num of retries for broken syslogs */
pub const SLOG_SEND_MAIL: libc::c_int = 0x08;
pub const SLOG_NO_LOG: libc::c_int = 0x20;
pub const SUDO_LOCK: libc::c_int = 1;
pub const FLAG_NO_USER: libc::c_int = 0x020;
pub const FLAG_NO_HOST: libc::c_int = 0x040;
pub const PERM_ROOT: libc::c_int = 0x01;
pub const SUDO_CONV_ERROR_MSG: libc::c_int = 0x0003;
pub const FLAG_NO_CHECK: libc::c_int = 0x080;
pub const NOT_FOUND_DOT: libc::c_int = 2;
pub const NOT_FOUND: libc::c_int = 1;
pub const VALIDATE_SUCCESS: libc::c_int = 0x002;
pub const INCORRECT_PASSWORD_ATTEMPT: libc::c_int = 0x01;
pub const FLAG_NON_INTERACTIVE: libc::c_int = 0x100;
pub const NBBY: libc::c_int = 8;
pub const MAX_MAILFLAGS: usize = 63;
pub const PERM_FULL_USER: libc::c_int = 0x03;
pub const STDIN_FILENO: libc::c_int = 0;
pub const LOG_ERR: libc::c_int = 3;
pub const VALIDATE_ERROR: libc::c_int = 0x001;

pub type nl_item = libc::c_int;
pub type __builtin_va_list = [__va_list_tag; 1];
#[derive(Copy, Clone)]
#[repr(C)]
pub struct __va_list_tag {
    pub gp_offset: libc::c_uint,
    pub fp_offset: libc::c_uint,
    pub overflow_arg_area: *mut libc::c_void,
    pub reg_save_area: *mut libc::c_void,
}

#[macro_export]
macro_rules! sudo_isset {
    ($_a:expr, $_i:expr) => {
        (*($_a).offset((($_i) / NBBY) as isize) & (1 << (($_i) % NBBY)))
    };
}

#[macro_export]
macro_rules! IS_SESSID {
    ($s:expr) => {
        isalnum!(*($s).offset(0 as isize)) != 0
            && isalnum!(*($s).offset(1 as isize)) != 0
            && *($s).offset(2 as isize) as libc::c_int == '/' as i32
            && isalnum!(*($s).offset(3 as isize)) != 0
            && isalnum!(*($s).offset(4 as isize)) != 0
            && *($s).offset(5 as isize) as libc::c_int == '/' as i32
            && isalnum!(*($s).offset(6 as isize)) != 0
            && isalnum!(*($s).offset(7 as isize)) != 0
            && *($s).offset(8 as isize) as libc::c_int == '\0' as i32
    };
}

#[macro_export]
macro_rules! LL_TTY_STR {
    () => {
        b"TTY=\0" as *const u8 as *const libc::c_char
    };
}
#[macro_export]
macro_rules! LL_CWD_STR {
    () => {
        b"PWD=\0" as *const u8 as *const libc::c_char
    };
}
#[macro_export]
macro_rules! LL_USER_STR {
    () => {
        b"USER=\0" as *const u8 as *const libc::c_char
    };
}
#[macro_export]
macro_rules! LL_GROUP_STR {
    () => {
        b"GROUP=\0" as *const u8 as *const libc::c_char
    };
}
#[macro_export]
macro_rules! LL_TSID_STR {
    () => {
        b"TSID=\0" as *const u8 as *const libc::c_char
    };
}
#[macro_export]
macro_rules! LL_ENV_STR {
    () => {
        b"ENV=\0" as *const u8 as *const libc::c_char
    };
}
#[macro_export]
macro_rules! LL_CMND_STR {
    () => {
        b"COMMAND=\0" as *const u8 as *const libc::c_char
    };
}

/*
 * Log a message to syslog, pre-pending the username and splitting the
 * message into parts if it is longer than syslog_maxlen.
 */
#[no_mangle]
fn do_syslog(mut pri: libc::c_int, mut msg: *mut libc::c_char) {
    let mut len: size_t = 0;
    let mut maxlen: size_t = 0;
    let mut p: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut tmp: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut save: libc::c_char = 0;
    let mut fmt: *const libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut oldlocale: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        /* A priority of -1 corresponds to "none". */
        if pri == -(1 as libc::c_int) {
            debug_return!();
        }

        sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &mut oldlocale);

        /*
         * Log the full line, breaking into multiple syslog(3) calls if necessary
         */
        fmt = dcgettext(
            b"sudoers\0" as *const u8 as *const libc::c_char,
            b"%8s : %s\0" as *const u8 as *const libc::c_char,
            5 as libc::c_int,
        );
        maxlen = (def_syslog_maxlen!() as libc::c_ulong).wrapping_sub(
            (strlen(fmt))
                .wrapping_sub(5 as libc::c_int as libc::c_ulong)
                .wrapping_add(strlen((*sudo_user.pw).pw_name)),
        );
        p = msg;
        while *p as libc::c_int != '\0' as i32 {
            len = strlen(p);
            if len > maxlen {
                /*
                 * Break up the line into what will fit on one syslog(3) line
                 * Try to avoid breaking words into several lines if possible.
                 */
                tmp = memrchr(p as *const libc::c_void, ' ' as i32, maxlen) as *mut libc::c_char;
                if tmp.is_null() {
                    tmp = p.offset(maxlen as isize);
                }

                /* NULL terminate line, but save the char to restore later */
                save = *tmp;
                *tmp = '\0' as i32 as libc::c_char;

                mysyslog(pri, fmt, (*sudo_user.pw).pw_name, p);

                *tmp = save; /* restore saved character */

                /* Advance p and eliminate leading whitespace */
                p = tmp;
                while *p as libc::c_int == ' ' as i32 {
                    p = p.offset(1);
                }
            } else {
                mysyslog(pri, fmt, (*sudo_user.pw).pw_name, p);
                p = p.offset(len as isize);
            }
            fmt = dcgettext(
                b"sudoers\0" as *const u8 as *const libc::c_char,
                b"%8s : (command continued) %s\0" as *const u8 as *const libc::c_char,
                5 as libc::c_int,
            );
            maxlen = (def_syslog_maxlen!() as libc::c_ulong).wrapping_sub(
                (strlen(fmt))
                    .wrapping_sub(5 as libc::c_int as libc::c_ulong)
                    .wrapping_add(strlen((*sudo_user.pw).pw_name)),
            );
        }

        sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());

        debug_return!();
    } //unsafe
}

#[no_mangle]
fn do_logfile(mut msg: *const libc::c_char) -> bool {
    static mut warned: bool = false;
    let mut timestr: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut len: libc::c_int = 0;
    let mut oldlocale: libc::c_int = 0;
    let mut ret: bool = false;
    let mut full_line: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut oldmask: mode_t = 0;
    let mut fp: *mut FILE = std::ptr::null_mut::<FILE>();
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &mut oldlocale);

        oldmask = umask((S_IRWXG | S_IRWXO) as __mode_t);
        fp = fopen(def_logfile!(), b"a\0" as *const u8 as *const libc::c_char);
        umask(oldmask);
        'done: loop {
            if fp.is_null() {
                if !warned {
                    log_warning(
                        SLOG_SEND_MAIL | SLOG_NO_LOG,
                        b"unable to open log file: %s\0" as *const u8 as *const libc::c_char,
                        def_logfile!(),
                    );
                    warned = true;
                }
                break 'done;
            }
            if !sudo_lock_file_v1(fileno(fp), SUDO_LOCK) {
                if !warned {
                    log_warning(
                        SLOG_SEND_MAIL | SLOG_NO_LOG,
                        b"unable to lock log file: %s\0" as *const u8 as *const libc::c_char,
                        def_logfile!(),
                    );
                    warned = true;
                }
                break 'done;
            }

            timestr = get_timestr(time(std::ptr::null_mut::<time_t>()), def_log_year!());
            if timestr.is_null() {
                timestr = b"invalid date\0" as *const u8 as *const libc::c_char;
            }
            if def_log_host!() != 0 {
                len = asprintf(
                    &mut full_line as *mut *mut libc::c_char,
                    b"%s : %s : HOST=%s : %s\0" as *const u8 as *const libc::c_char,
                    timestr,
                    (*sudo_user.pw).pw_name,
                    sudo_user.srunhost,
                    msg,
                );
            } else {
                len = asprintf(
                    &mut full_line as *mut *mut libc::c_char,
                    b"%s : %s : %s\0" as *const u8 as *const libc::c_char,
                    timestr,
                    (*sudo_user.pw).pw_name,
                    msg,
                );
            }
            if len == -(1 as libc::c_int) {
                sudo_warnx!(
                    b"%s: %s\0" as *const u8 as *const libc::c_char,
                    get_function_name!(),
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                );
                break 'done;
            }
            if (def_loglinelen!() as size_t)
                < ::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong
            {
                /* Don't pretty-print long log file lines (hard to grep). */
                fputs(full_line, fp);
                fputc('\n' as i32, fp);
            } else {
                /* Write line with word wrap around def_loglinelen chars. */
                writeln_wrap(fp, full_line, len as size_t, def_loglinelen!() as size_t);
            }
            free(full_line as *mut libc::c_void);
            fflush(fp);
            if ferror(fp) != 0 {
                if !warned {
                    log_warning(
                        SLOG_SEND_MAIL | SLOG_NO_LOG,
                        b"unable to write log file: %s\0" as *const u8 as *const libc::c_char,
                        def_logfile!(),
                    );
                    warned = true;
                }
                break 'done;
            }
            ret = true;
            break;
        }

        //done:
        if !fp.is_null() {
            fclose(fp);
        }
        sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());

        debug_return_bool!(ret);
    } //unsafe
}

/*
 * Log, audit and mail the denial message, optionally informing the user.
 */
#[no_mangle]
pub fn log_denial(mut status: libc::c_int, mut inform_user: bool) -> bool {
    let mut message: *const libc::c_char = std::ptr::null::<libc::c_char>();
    let mut logline: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut oldlocale: libc::c_int = 0;
    let mut uid_changed: bool = false;
    let mut ret: bool = true;
    let mut mailit: bool = false;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        /* Handle auditing first (audit_failure() handles the locale itself). */
        if ISSET!(status, FLAG_NO_USER | FLAG_NO_HOST) != 0 {
            audit_failure(
                NewArgc,
                NewArgv,
                b"No user or host\0" as *const u8 as *const libc::c_char,
            );
        } else {
            audit_failure(
                NewArgc,
                NewArgv,
                b"validation failure\0" as *const u8 as *const libc::c_char,
            );
        }

        /* Send mail based on status. */
        mailit = should_mail(status);

        if def_log_denied!() != 0 || mailit as libc::c_int != 0 {
            /* Log and mail messages should be in the sudoers locale. */
            sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &mut oldlocale);

            /* Set error message. */
            if ISSET!(status, FLAG_NO_USER) != 0 {
                message = dcgettext(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"user NOT in sudoers\0" as *const u8 as *const libc::c_char,
                    5 as libc::c_int,
                );
            } else if ISSET!(status, FLAG_NO_HOST) != 0 {
                message = dcgettext(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"user NOT authorized on host\0" as *const u8 as *const libc::c_char,
                    5 as libc::c_int,
                );
            } else {
                message = dcgettext(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"command not allowed\0" as *const u8 as *const libc::c_char,
                    5 as libc::c_int,
                );
            }

            logline = new_logline(message, std::ptr::null::<libc::c_char>());
            if logline.is_null() {
                debug_return_bool!(false);
            }

            /* Become root if we are not already. */
            uid_changed = set_perms(PERM_ROOT);

            if mailit {
                send_mail(b"%s\0" as *const u8 as *const libc::c_char, logline);
                /* XXX - return value */
            }

            /* Log via syslog and/or a file. */
            if def_log_denied!() != 0 {
                if def_syslog!() != 0 {
                    do_syslog(def_syslog_badpri!(), logline);
                }
                if !(def_logfile!()).is_null() && !do_logfile(logline) {
                    ret = false;
                }
            }

            /*if uid_changed {
                if !restore_perms() {
                    ret = false; /* XXX - return -1 instead? */
                }
            }*/
            if uid_changed && !restore_perms() {
                ret = false; /* XXX - return -1 instead? */
            }

            free(logline as *mut libc::c_void);

            /* Restore locale. */
            sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());
        }

        /* Inform the user if they failed to authenticate (in their locale).  */
        if inform_user {
            sudoers_setlocale(SUDOERS_LOCALE_USER, &mut oldlocale);

            if ISSET!(status, FLAG_NO_USER) != 0 {
                sudo_printf.expect("non-null function pointer")(
                    SUDO_CONV_ERROR_MSG,
                    dcgettext(
                        b"sudoers\0" as *const u8 as *const libc::c_char,
                        b"%s is not in the utsudoers file.  This incident will be reported.\n\0"
                            as *const u8 as *const libc::c_char,
                        5 as libc::c_int,
                    ),
                    sudo_user.name,
                );
            } else if ISSET!(status, FLAG_NO_HOST) != 0 {
                sudo_printf.expect("non-null function pointer")(
                    SUDO_CONV_ERROR_MSG,
                    dcgettext(
                        b"sudoers\0" as *const u8 as *const libc::c_char,
                        b"%s is not allowed to run sudo on %s.  This incident will be reported.\n\0"
                            as *const u8 as *const libc::c_char,
                        5 as libc::c_int,
                    ),
                    sudo_user.name,
                    sudo_user.srunhost,
                );
            } else if ISSET!(status, FLAG_NO_CHECK) != 0 {
                sudo_printf.expect("non-null function pointer")(
                    SUDO_CONV_ERROR_MSG,
                    dcgettext(
                        b"sudoers\0" as *const u8 as *const libc::c_char,
                        b"Sorry, user %s may not run sudo on %s.\n\0" as *const u8
                            as *const libc::c_char,
                        5 as libc::c_int,
                    ),
                    sudo_user.name,
                    sudo_user.srunhost,
                );
            } else {
                sudo_printf.expect("non-null function pointer")(
                    SUDO_CONV_ERROR_MSG,
                    dcgettext(
                        b"sudoers\0" as *const u8 as *const libc::c_char,
                        b"Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n\0"
                            as *const u8 as *const libc::c_char,
                        5 as libc::c_int,
                    ),
                    sudo_user.name,
                    sudo_user.cmnd,
                    if !(sudo_user.cmnd_args).is_null() {
                        b" \0" as *const u8 as *const libc::c_char
                    } else {
                        b"\0" as *const u8 as *const libc::c_char
                    },
                    if !(sudo_user.cmnd_args).is_null() {
                        sudo_user.cmnd_args as *const libc::c_char
                    } else {
                        b"\0" as *const u8 as *const libc::c_char
                    },
                    if !list_pw.is_null() {
                        (*list_pw).pw_name
                    } else if !(sudo_user._runas_pw).is_null() {
                        (*sudo_user._runas_pw).pw_name
                    } else {
                        sudo_user.name
                    },
                    if !(sudo_user._runas_gr).is_null() {
                        b":\0" as *const u8 as *const libc::c_char
                    } else {
                        b"\0" as *const u8 as *const libc::c_char
                    },
                    if !(sudo_user._runas_gr).is_null() {
                        (*sudo_user._runas_gr).gr_name as *const libc::c_char
                    } else {
                        b"\0" as *const u8 as *const libc::c_char
                    },
                    sudo_user.host,
                );
            }
            sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());
        }
        debug_return_bool!(ret);
    } //unsafe
}

/*
 * Log and audit that user was not allowed to run the command.
 */
#[no_mangle]
pub fn log_failure(mut status: libc::c_int, mut flags: libc::c_int) -> bool {
    let mut ret: bool = false;
    let mut inform_user: bool = true;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        /* The user doesn't always get to see the log message (path info). */
        if ISSET!(status, FLAG_NO_USER | FLAG_NO_HOST) == 0
            && def_path_info!() != 0
            && (flags == NOT_FOUND_DOT || flags == NOT_FOUND)
        {
            inform_user = false;
        }
        ret = log_denial(status, inform_user);

        if !inform_user {
            /*
             * We'd like to not leak path info at all here, but that can
             * *really* confuse the users.  To really close the leak we'd
             * have to say "not allowed to run foo" even when the problem
             * is just "no foo in path" since the user can trivially set
             * their path to just contain a single dir.
             */
            if flags == NOT_FOUND {
                sudo_warnx!(
                    b"%s: command not found\0" as *const u8 as *const libc::c_char,
                    sudo_user.cmnd
                );
            } else if flags == NOT_FOUND_DOT {
                sudo_warnx!(
            b"ignoring \"%s\" found in '.'\nUse \"sudo ./%s\" if this is the \"%s\" you wish to run.\0" as *const u8 as *const libc::c_char,
            sudo_user.cmnd,
            sudo_user.cmnd,
            sudo_user.cmnd
        );
            }
        }

        debug_return_bool!(ret);
    } //unsafe
}

/*
 * Log and audit that user was not able to authenticate themselves.
 */
#[no_mangle]
pub fn log_auth_failure(mut status: libc::c_int, mut tries: libc::c_uint) -> bool {
    let mut flags: libc::c_int = 0 as libc::c_int;
    let mut ret: bool = true;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        /* Handle auditing first. */
        audit_failure(
            NewArgc,
            NewArgv,
            b"authentication failure\0" as *const u8 as *const libc::c_char,
        );

        /*
         * Do we need to send mail?
         * We want to avoid sending multiple messages for the same command
         * so if we are going to send an email about the denial, that takes
         * precedence.
         */
        if ISSET!(status, VALIDATE_SUCCESS) != 0 {
            /* Command allowed, auth failed; do we need to send mail? */
            if def_mail_badpass!() != 0 || def_mail_always!() != 0 {
                SET!(flags, SLOG_SEND_MAIL);
            }
        } else {
            /* Command denied, auth failed; make sure we don't send mail twice. */
            if def_mail_badpass!() != 0 && !should_mail(status) {
                SET!(flags, SLOG_SEND_MAIL);
            }
            /* Don't log the bad password message, we'll log a denial instead. */
            SET!(flags, SLOG_NO_LOG);
        }

        /*
         * If sudoers denied the command we'll log that separately.
         */
        if ISSET!(status, FLAG_BAD_PASSWORD) != 0 {
            ret = log_warningx(
                flags,
                INCORRECT_PASSWORD_ATTEMPT as *mut libc::c_char,
                tries,
            );
        } else if ISSET!(status, FLAG_NON_INTERACTIVE) != 0 {
            ret = log_warningx(
                flags,
                b"a password is required\0" as *const u8 as *const libc::c_char,
            );
        }

        debug_return_bool!(ret);
    } //unsafe
}

/*
 * Log and potentially mail the allowed command.
 */
#[no_mangle]
pub fn log_allowed(mut status: libc::c_int) -> bool {
    let mut logline: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut oldlocale: libc::c_int = 0;
    let mut uid_changed: bool = false;
    let mut ret: bool = true;
    let mut mailit: bool = false;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());
    }

    /* Send mail based on status. */
    unsafe {
        mailit = should_mail(status);

        if def_log_allowed!() != 0 || mailit as libc::c_int != 0 {
            /* Log and mail messages should be in the sudoers locale. */
            sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &mut oldlocale);

            logline = new_logline(
                std::ptr::null::<libc::c_char>(),
                std::ptr::null::<libc::c_char>(),
            );
            if logline.is_null() {
                debug_return_bool!(false);
            }

            /* Become root if we are not already. */
            uid_changed = set_perms(PERM_ROOT);

            if mailit {
                send_mail(b"%s\0" as *const u8 as *const libc::c_char, logline);
                /* XXX - return value */
            }

            /*
             * Log via syslog and/or a file.
             */
            if def_log_allowed!() != 0 {
                if def_syslog!() != 0 {
                    do_syslog(def_syslog_goodpri!(), logline);
                }
                if !(def_logfile!()).is_null() && !do_logfile(logline) {
                    ret = false;
                }
            }

            /*if uid_changed {
                if !restore_perms() {
                    ret = false; /* XXX - return -1 instead? */
                }
            }*/
            if uid_changed && !restore_perms() {
                ret = false; /* XXX - return -1 instead? */
            }

            free(logline as *mut libc::c_void);

            sudoers_setlocale(oldlocale, std::ptr::null_mut::<libc::c_int>());
        }

        debug_return_bool!(ret);
    } //unsafe
}

#[no_mangle]
fn closefrom_nodebug(mut lowfd: libc::c_int) {
    let mut debug_fds: *mut libc::c_uchar = std::ptr::null_mut::<libc::c_uchar>();
    let mut fd: libc::c_int = 0;
    let mut startfd: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        startfd = sudo_debug_get_fds_v1(&mut debug_fds) + 1 as libc::c_int;
        if lowfd > startfd {
            startfd = lowfd;
        }

        /* Close fds higher than the debug fds. */
        sudo_debug_printf!(
            SUDO_DEBUG_DEBUG | SUDO_DEBUG_LINENO,
            b"closing fds >= %d\0" as *const u8 as *const libc::c_char,
            startfd
        );
        sudo_closefrom(startfd);

        /* Close fds [lowfd, startfd) that are not in debug_fds. */
        fd = lowfd;
        while fd < startfd {
            if sudo_isset!(debug_fds, fd) == 0 {
                sudo_debug_printf!(
                    SUDO_DEBUG_DEBUG | SUDO_DEBUG_LINENO,
                    b"closing fds >= %d\0" as *const u8 as *const libc::c_char,
                    fd
                );
                close(fd);
            }
            fd += 1;
        }
        debug_return!();
    } //unsafe
}

#[no_mangle]
fn exec_mailer(mut pfd: *mut libc::c_int) -> ! {
    let mut last: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut p: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut argv: [*mut libc::c_char; MAX_MAILFLAGS + 1] =
        [std::ptr::null_mut::<libc::c_char>(); MAX_MAILFLAGS + 1];
    let mut mflags: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    unsafe {
        let mut mpath: *mut libc::c_char = def_mailerpath!();
        let mut i: libc::c_int = 0;
        let mut perm: libc::c_int = PERM_FULL_USER;
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        /* Set stdin to output side of the pipe */
        if *pfd.offset(0_isize) != STDIN_FILENO {
            if dup2(*pfd.offset(0_isize), STDIN_FILENO) == -(1 as libc::c_int) {
                mysyslog(
                    LOG_ERR,
                    dcgettext(
                        b"sudoers\0" as *const u8 as *const libc::c_char,
                        b"unable to dup stdin: %m\0" as *const u8 as *const libc::c_char,
                        5 as libc::c_int,
                    ),
                );
                sudo_debug_printf!(
                    SUDO_DEBUG_ERROR,
                    b"unable to dup stdin: %s\0" as *const u8 as *const libc::c_char,
                    strerror(*__errno_location())
                );
                sudo_debug_exit_v1(
                    get_function_name!(),
                    get_file_name!(),
                    line!() as libc::c_int,
                    sudo_debug_subsys as libc::c_int,
                );
                _exit(127 as libc::c_int);
            }
            close(*pfd.offset(0 as libc::c_int as isize));
        }
        close(*pfd.offset(1 as libc::c_int as isize));

        /* Build up an argv based on the mailer path and flags */
        mflags = strdup(def_mailerflags!());
        if mflags.is_null() {
            mysyslog(
                LOG_ERR,
                dcgettext(
                    b"sudoers\0" as *const u8 as *const libc::c_char,
                    b"unable to allocate memory\0" as *const u8 as *const libc::c_char,
                    5 as libc::c_int,
                ),
            );
            sudo_debug_exit_v1(
                get_function_name!(),
                get_file_name!(),
                line!() as libc::c_int,
                sudo_debug_subsys as libc::c_int,
            );
            _exit(127);
        }
        argv[0_usize] = strrchr(mpath, '/' as i32);
        if !(argv[0_usize]).is_null() {
            argv[0_usize] = (argv[0_usize]).offset(1);
        } else {
            argv[0_usize] = mpath;
        }

        i = 1 as libc::c_int;
        p = strtok_r(
            mflags,
            b" \t\0" as *const u8 as *const libc::c_char,
            &mut last,
        );
        if !p.is_null() {
            loop {
                argv[i as usize] = p;
                i += 1;
                if !(i < MAX_MAILFLAGS as libc::c_int && {
                    p = strtok_r(
                        std::ptr::null_mut::<libc::c_char>(),
                        b" \t\0" as *const u8 as *const libc::c_char,
                        &mut last,
                    );
                    !p.is_null()
                }) {
                    break;
                }
            }
        }
        argv[i as usize] = std::ptr::null_mut::<libc::c_char>();

        /*
         * Depending on the config, either run the mailer as root
         * (so user cannot kill it) or as the user (for the paranoid).
         */
        set_perms(perm);
        sudo_debug_exit_v1(
            get_function_name!(),
            get_file_name!(),
            line!() as libc::c_int,
            sudo_debug_subsys as libc::c_int,
        );
        execv(mpath, argv.as_mut_ptr() as *const *mut libc::c_char);
        mysyslog(
            LOG_ERR,
            dcgettext(
                b"sudoers\0" as *const u8 as *const libc::c_char,
                b"unable to execute %s: %m\0" as *const u8 as *const libc::c_char,
                5 as libc::c_int,
            ),
            mpath,
        );
        sudo_debug_printf!(
            SUDO_DEBUG_ERROR,
            b"unable to execute %s: %s\0" as *const u8 as *const libc::c_char,
            mpath,
            strerror(*__errno_location())
        );
        _exit(127);
    } //unsafe
}

/*
 * Determine whether we should send mail based on "status" and defaults options.
 */
fn should_mail(mut status: libc::c_int) -> bool {
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        debug_return_bool!(
            def_mail_always!() != 0
                || ISSET!(status, VALIDATE_ERROR) != 0
                || (def_mail_all_cmnds!() != 0 && ISSET!(sudo_mode, (MODE_RUN | MODE_EDIT)) != 0)
                || (def_mail_no_user!() != 0 && ISSET!(status, FLAG_NO_USER) != 0)
                || (def_mail_no_host!() != 0 && ISSET!(status, FLAG_NO_HOST) != 0)
                || (def_mail_no_perms!() != 0 && ISSET!(status, VALIDATE_SUCCESS) == 0)
        );
    } //unsafe
}

/*
 * Allocate and fill in a new logline.
 */
#[no_mangle]
fn new_logline(
    mut message: *const libc::c_char,
    mut errstr: *const libc::c_char,
) -> *mut libc::c_char {
    let mut line: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut evstr: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut sessid: [libc::c_char; 7] = [0; 7];
    let mut tsid: *const libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut len: size_t = 0 as libc::c_int as size_t;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_LOGGING!());

        /* A TSID may be a sudoers-style session ID or a free-form string. */
        if !(sudo_user.iolog_file).is_null() {
            if IS_SESSID!(sudo_user.iolog_file) {
                sessid[0 as libc::c_int as usize] =
                    *(sudo_user.iolog_file).offset(0 as libc::c_int as isize);
                sessid[1 as libc::c_int as usize] =
                    *(sudo_user.iolog_file).offset(1 as libc::c_int as isize);
                sessid[2 as libc::c_int as usize] =
                    *(sudo_user.iolog_file).offset(3 as libc::c_int as isize);
                sessid[3 as libc::c_int as usize] =
                    *(sudo_user.iolog_file).offset(4 as libc::c_int as isize);
                sessid[4 as libc::c_int as usize] =
                    *(sudo_user.iolog_file).offset(6 as libc::c_int as isize);
                sessid[5 as libc::c_int as usize] =
                    *(sudo_user.iolog_file).offset(7 as libc::c_int as isize);
                sessid[6 as libc::c_int as usize] = '\0' as i32 as libc::c_char;
                tsid = sessid.as_mut_ptr();
            } else {
                tsid = sudo_user.iolog_file;
            }
        }

        /*
         * Compute line length
         */
        if !message.is_null() {
            len = (len as libc::c_ulong)
                .wrapping_add((strlen(message)).wrapping_add(3 as libc::c_int as libc::c_ulong))
                as size_t as size_t;
        }
        if !errstr.is_null() {
            len = (len as libc::c_ulong)
                .wrapping_add((strlen(errstr)).wrapping_add(3 as libc::c_int as libc::c_ulong))
                as size_t as size_t;
        }
        len = (len as libc::c_ulong).wrapping_add(
            (::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong)
                .wrapping_add(2 as libc::c_int as libc::c_ulong)
                .wrapping_add(strlen(sudo_user.tty)),
        ) as size_t as size_t;
        len = (len as libc::c_ulong).wrapping_add(
            (::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong)
                .wrapping_add(2 as libc::c_int as libc::c_ulong)
                .wrapping_add(strlen(sudo_user.cwd)),
        ) as size_t as size_t;
        if !(sudo_user._runas_pw).is_null() {
            len = (len as libc::c_ulong).wrapping_add(
                (::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong)
                    .wrapping_add(2 as libc::c_int as libc::c_ulong)
                    .wrapping_add(strlen((*sudo_user._runas_pw).pw_name)),
            ) as size_t as size_t;
        }
        if !(sudo_user._runas_gr).is_null() {
            len = (len as libc::c_ulong).wrapping_add(
                (::core::mem::size_of::<[libc::c_char; 7]>() as libc::c_ulong)
                    .wrapping_add(2 as libc::c_int as libc::c_ulong)
                    .wrapping_add(strlen((*sudo_user._runas_gr).gr_name)),
            ) as size_t as size_t;
        }
        if !tsid.is_null() {
            len = (len as libc::c_ulong).wrapping_add(
                (::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong)
                    .wrapping_add(2 as libc::c_int as libc::c_ulong)
                    .wrapping_add(strlen(tsid)),
            ) as size_t as size_t;
        }

        'toobig: loop {
            'oom: loop {
                if !(sudo_user.env_vars).is_null() {
                    let mut evlen: size_t = 0 as libc::c_int as size_t;
                    let mut ep: *const *mut libc::c_char = std::ptr::null::<*mut libc::c_char>();

                    ep = sudo_user.env_vars;
                    while !(*ep).is_null() {
                        evlen = (evlen as libc::c_ulong).wrapping_add(
                            (strlen(*ep)).wrapping_add(1 as libc::c_int as libc::c_ulong),
                        ) as size_t as size_t;
                        ep = ep.offset(1);
                    }
                    if evlen != 0 as libc::c_int as libc::c_ulong {
                        evstr = malloc(evlen) as *mut libc::c_char;
                        if evstr.is_null() {
                            break 'oom;
                        }
                        *evstr.offset(0 as libc::c_int as isize) = '\0' as i32 as libc::c_char;
                        ep = sudo_user.env_vars;
                        while !(*ep).is_null() {
                            sudo_strlcat(evstr, *ep, evlen);
                            sudo_strlcat(evstr, b" \0" as *const u8 as *const libc::c_char, evlen); /* NOTE: last one will fail */
                            ep = ep.offset(1);
                        }
                        len = (len as libc::c_ulong).wrapping_add(
                            (::core::mem::size_of::<[libc::c_char; 5]>() as libc::c_ulong)
                                .wrapping_add(2 as libc::c_int as libc::c_ulong)
                                .wrapping_add(evlen),
                        ) as size_t as size_t;
                    }
                }
                if !(sudo_user.cmnd).is_null() {
                    /* Note: we log "sudo -l command arg ..." as "list command arg ..." */
                    len = (len as libc::c_ulong).wrapping_add(
                        (::core::mem::size_of::<[libc::c_char; 9]>() as libc::c_ulong)
                            .wrapping_sub(1 as libc::c_int as libc::c_ulong)
                            .wrapping_add(strlen(sudo_user.cmnd)),
                    ) as size_t as size_t;
                    if ISSET!(sudo_mode, MODE_CHECK) != 0 {
                        len = (len as libc::c_ulong).wrapping_add(
                            (::core::mem::size_of::<[libc::c_char; 6]>() as libc::c_ulong)
                                .wrapping_sub(1 as libc::c_int as libc::c_ulong),
                        ) as size_t as size_t;
                    }
                    if !(sudo_user.cmnd_args).is_null() {
                        len = (len as libc::c_ulong).wrapping_add(
                            (strlen(sudo_user.cmnd_args))
                                .wrapping_add(1 as libc::c_int as libc::c_ulong),
                        ) as size_t as size_t;
                    }
                }

                /*
                 * Allocate and build up the line.
                 */
                len = len.wrapping_add(1);
                line = malloc(len) as *mut libc::c_char;
                if line.is_null() {
                    break 'oom;
                }
                *line.offset(0 as libc::c_int as isize) = '\0' as i32 as libc::c_char;

                if !message.is_null()
                    && (sudo_strlcat(line, message, len) >= len
                        || sudo_strlcat(
                            line,
                            if !errstr.is_null() {
                                b" : \0" as *const u8 as *const libc::c_char
                            } else {
                                b" ; \0" as *const u8 as *const libc::c_char
                            },
                            len,
                        ) >= len)
                {
                    break 'toobig;
                }

                /*if !message.is_null() {
                    if sudo_strlcat(line, message, len) >= len
                        || sudo_strlcat(
                            line,
                            if !errstr.is_null() {
                                b" : \0" as *const u8 as *const libc::c_char
                            } else {
                                b" ; \0" as *const u8 as *const libc::c_char
                            },
                            len,
                        ) >= len
                    {
                        break 'toobig;
                    }
                }*/

                if !errstr.is_null()
                    && (sudo_strlcat(line, errstr, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len)
                {
                    break 'toobig;
                }

                /*if !errstr.is_null() {
                    if sudo_strlcat(line, errstr, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len
                    {
                        break 'toobig;
                    }
                }*/
                if sudo_strlcat(line, LL_TTY_STR!(), len) >= len
                    || sudo_strlcat(line, sudo_user.tty, len) >= len
                    || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len) >= len
                {
                    break 'toobig;
                }
                if sudo_strlcat(line, LL_CWD_STR!(), len) >= len
                    || sudo_strlcat(line, sudo_user.cwd, len) >= len
                    || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len) >= len
                {
                    break 'toobig;
                }
                if !(sudo_user._runas_pw).is_null()
                    && (sudo_strlcat(line, LL_USER_STR!(), len) >= len
                        || sudo_strlcat(line, (*sudo_user._runas_pw).pw_name, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len)
                {
                    break 'toobig;
                }

                /*if !(sudo_user._runas_pw).is_null() {
                    if sudo_strlcat(line, LL_USER_STR!(), len) >= len
                        || sudo_strlcat(line, (*sudo_user._runas_pw).pw_name, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len
                    {
                        break 'toobig;
                    }
                }*/

                if !(sudo_user._runas_gr).is_null()
                    && (sudo_strlcat(line, LL_GROUP_STR!(), len) >= len
                        || sudo_strlcat(line, (*sudo_user._runas_gr).gr_name, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len)
                {
                    break 'toobig;
                }

                /*if !(sudo_user._runas_gr).is_null() {
                    if sudo_strlcat(line, LL_GROUP_STR!(), len) >= len
                        || sudo_strlcat(line, (*sudo_user._runas_gr).gr_name, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len
                    {
                        break 'toobig;
                    }
                }*/

                if !tsid.is_null()
                    && (sudo_strlcat(line, LL_TSID_STR!(), len) >= len
                        || sudo_strlcat(line, tsid, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len)
                {
                    break 'toobig;
                }

                /*if !tsid.is_null() {
                    if sudo_strlcat(line, LL_TSID_STR!(), len) >= len
                        || sudo_strlcat(line, tsid, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len
                    {
                        break 'toobig;
                    }
                }*/
                if !evstr.is_null() {
                    if sudo_strlcat(line, LL_ENV_STR!(), len) >= len
                        || sudo_strlcat(line, evstr, len) >= len
                        || sudo_strlcat(line, b" ; \0" as *const u8 as *const libc::c_char, len)
                            >= len
                    {
                        break 'toobig;
                    }
                    free(evstr as *mut libc::c_void);
                    evstr = std::ptr::null_mut::<libc::c_char>();
                }
                if !(sudo_user.cmnd).is_null() {
                    if sudo_strlcat(line, LL_CMND_STR!(), len) >= len {
                        break 'toobig;
                    }
                    if ISSET!(sudo_mode, MODE_CHECK) != 0
                        && sudo_strlcat(line, b"list \0" as *const u8 as *const libc::c_char, len)
                            >= len
                    {
                        break 'toobig;
                    }
                    if sudo_strlcat(line, sudo_user.cmnd, len) >= len {
                        break 'toobig;
                    }
                    /*if !(sudo_user.cmnd_args).is_null() {
                        if sudo_strlcat(line, b" \0" as *const u8 as *const libc::c_char, len)
                            >= len
                            || sudo_strlcat(line, sudo_user.cmnd_args, len) >= len
                        {
                            break 'toobig;
                        }
                    }*/
                    if !(sudo_user.cmnd_args).is_null()
                        && (sudo_strlcat(line, b" \0" as *const u8 as *const libc::c_char, len)
                            >= len
                            || sudo_strlcat(line, sudo_user.cmnd_args, len) >= len)
                    {
                        break 'toobig;
                    }
                }

                debug_return_str!(line);
            }
            //oom:
            free(evstr as *mut libc::c_void);
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            debug_return_str!(std::ptr::null_mut::<libc::c_char>());
        }
        //toobig
        free(evstr as *mut libc::c_void);
        free(line as *mut libc::c_void);
        sudo_warnx!(
            b"internal error, %s overflow\0" as *const u8 as *const libc::c_char,
            get_function_name!()
        );
        debug_return_str!(std::ptr::null_mut::<libc::c_char>());
    } //unsafe
}
